Add fix, course, and speed options to track filter
authorparkrrrr <parkrrrr@f51c46e8-681c-474f-0cfe-069cfd0219fb>
Fri, 7 Apr 2006 14:53:15 +0000 (14:53 +0000)
committerparkrrrr <parkrrrr@f51c46e8-681c-474f-0cfe-069cfd0219fb>
Fri, 7 Apr 2006 14:53:15 +0000 (14:53 +0000)
gpsbabel/readme.xml
gpsbabel/trackfilter.c

index ee64a47901998e13b14cfd6ad3a621d6e4b932a1..1b6e9a03affc0a8c89540a177462c4103ce30e4f 100644 (file)
@@ -2021,7 +2021,7 @@ gpsbabel -i gpx -f indiana.gpx \
 </screen>
       </section>
       <section>
-         <title> TRACK</title>
+         <title>TRACK</title>
          <para> ( !!! This filter always drops empty tracks !!! )
          </para>
          <para>The track filter is a tool for manipulating track lists.  The
@@ -2112,6 +2112,36 @@ gpsbabel -t \
      -x track,merge,title="COMBINED LOG" \
      -o gpx -F john_doe.gpx
 </screen>
+       <para>FIX</para>
+       <para>Fix forces the GPS fix status for all trackpoints to the 
+        specified value.  The value may be PPS, DGPS, 3D, 2D, or NONE.
+       </para>
+       <screen format="linespecific">
+       gpsbabel -i gpx -f trk.gpx -x track,fix=3D -o nmea -F -
+       </screen>
+
+       <para>COURSE</para>
+       <para>Course computes a value for the GPS heading at each trackpoint.
+       This is most useful with trackpoints from formats that don't support
+       heading information or for trackpoints synthesized by the interpolate
+       filter.  The heading at each trackpoint is simply the course from the
+       previous trackpoint in the track.  The first trackpoint in each track
+        is arbitrarily assigned a heading of 0 degrees.</para>
+       <screen format="linespecific">
+       gpsbabel -i gpx -f trk.gpx -x track,course,speed -o nmea -F -
+       </screen>
+
+       <para>SPEED</para>
+       <para>Course computes a value for the GPS speed at each trackpoint.
+       This is most useful with trackpoints from formats that don't support
+       speed information or for trackoints synthesized by the interpolate
+       filter.  The speed at each trackpoint is the average speed from the
+       previous trackpoint (distance/time).  The first trackpoint in each
+       track is assigned a speed of "unknown."</para>
+       <screen format="linespecific">
+       gpsbabel -i gpx -f trk.gpx -x track,course,speed -o nmea -F -
+       </screen>
+
       </section>
       <section>
          <title>DISCARD</title>
index 27625765c776f4c40694e15989cd829144bf8124..a4a57243243e60fe80fd4e12220bed1ad8a7fecd 100644 (file)
     2005-08-01: Add 'static' qualifier when we can (RJL)
     2005-10-04: Add filterdefs to hold protos for filter functions... (RJL)
     2005-10-04: Fix range-check max. value; exit filter, if no more tracks left
+    2006-04-06: Add fix, course, and speed options
  */
  
 #include <ctype.h>
 #include "defs.h"
 #include "filterdefs.h"
 #include "strptime.h"
+#include "grtcirc.h"
 
 #define MYNAME "trackfilter"
 
@@ -45,6 +47,9 @@
 #define TRACKFILTER_STOP_OPTION                "stop"
 #define TRACKFILTER_START_OPTION       "start"
 #define TRACKFILTER_MOVE_OPTION                "move"
+#define TRACKFILTER_FIX_OPTION          "fix"
+#define TRACKFILTER_COURSE_OPTION       "course"
+#define TRACKFILTER_SPEED_OPTION        "speed"
 
 #undef TRACKF_DBG
 
@@ -55,23 +60,38 @@ static char *opt_move = NULL;
 static char *opt_title = NULL;
 static char *opt_start = NULL;
 static char *opt_stop = NULL;
+static char *opt_fix = NULL;
+static char *opt_course = NULL;
+static char *opt_speed = NULL;
 
 static
 arglist_t trackfilter_args[] = {
        {TRACKFILTER_MOVE_OPTION, &opt_move, 
-           "Correct trackpoint timestamps by a delta", NULL, ARGTYPE_STRING, ARG_NOMINMAX},
+           "Correct trackpoint timestamps by a delta", NULL, ARGTYPE_STRING, 
+           ARG_NOMINMAX},
        {TRACKFILTER_PACK_OPTION,  &opt_pack,  
            "Pack all tracks into one", NULL, ARGTYPE_BOOL, ARG_NOMINMAX},
        {TRACKFILTER_SPLIT_OPTION, &opt_split, 
-           "Split track by date or by time interval (see README)", NULL, ARGTYPE_STRING, ARG_NOMINMAX},
+           "Split track by date or by time interval (see README)", NULL, 
+           ARGTYPE_STRING, ARG_NOMINMAX},
        {TRACKFILTER_MERGE_OPTION, &opt_merge, 
-           "Merge multiple tracks for the same way", NULL, ARGTYPE_STRING, ARG_NOMINMAX},
+           "Merge multiple tracks for the same way", NULL, ARGTYPE_STRING, 
+           ARG_NOMINMAX},
        {TRACKFILTER_START_OPTION, &opt_start, 
-           "Use only track points after this timestamp", NULL, ARGTYPE_INT, ARG_NOMINMAX},
+           "Use only track points after this timestamp", NULL, ARGTYPE_INT, 
+           ARG_NOMINMAX},
        {TRACKFILTER_STOP_OPTION, &opt_stop, 
-           "Use only track points before this timestamp", NULL, ARGTYPE_INT, ARG_NOMINMAX},
+           "Use only track points before this timestamp", NULL, ARGTYPE_INT, 
+           ARG_NOMINMAX},
        {TRACKFILTER_TITLE_OPTION, &opt_title, 
            "Basic title for new track(s)", NULL, ARGTYPE_STRING, ARG_NOMINMAX},
+       {TRACKFILTER_FIX_OPTION, &opt_fix,
+           "Synthesize GPS fixes (PPS, DGPS, 3D, 2D, NONE)", NULL,
+           ARGTYPE_STRING, ARG_NOMINMAX },
+       {TRACKFILTER_COURSE_OPTION, &opt_course, "Synthesize course",
+           NULL, ARGTYPE_BOOL, ARG_NOMINMAX },
+       {TRACKFILTER_SPEED_OPTION, &opt_speed, "Synthesize speed",
+            NULL, ARGTYPE_BOOL, ARG_NOMINMAX },
        ARG_TERMINATOR
 };
 
@@ -160,6 +180,30 @@ trackfilter_merge_qsort_cb(const void *a, const void *b)
        return wa->creation_time - wb->creation_time;
 }
 
+static fix_type
+trackfilter_parse_fix()
+{
+       if ( !opt_fix ) {
+               return fix_unknown;
+       }
+       if ( !case_ignore_strcmp( opt_fix, "pps" )) {
+               return fix_pps;
+       }
+       if ( !case_ignore_strcmp( opt_fix, "dgps" )) {
+               return fix_dgps;
+       }
+       if ( !case_ignore_strcmp( opt_fix, "3d" )) {
+               return fix_3d;
+       }
+       if ( !case_ignore_strcmp( opt_fix, "2d" )) {
+               return fix_2d;
+       }
+       if ( !case_ignore_strcmp( opt_fix, "none" )) {
+               return fix_none;
+       }
+       fatal( MYNAME ": invalid fix type\n" );
+}
+
 static void
 trackfilter_fill_track_list_cb(const route_head *track)        /* callback for track_disp_all */
 {
@@ -552,6 +596,70 @@ trackfilter_move(void)
        }
 }
 
+/*******************************************************************************
+* options "fix", "course", "speed"
+*******************************************************************************/
+
+static void
+trackfilter_synth(void)
+{
+       int i;
+       queue *elem, *tmp;
+       waypoint *wpt;
+       
+       double oldlat = -999;
+       double oldlon = -999;
+       time_t oldtime = 0;
+       int first = 1;
+       fix_type fix;
+       
+       fix = trackfilter_parse_fix();
+       
+       for (i = 0; i < track_ct; i++)
+       {
+           route_head *track = track_list[i].track;
+           first = 1;
+           QUEUE_FOR_EACH((queue *)&track->waypoint_list, elem, tmp)
+           {
+               wpt = (waypoint *)elem;
+               if ( opt_fix ) {
+                       wpt->fix = fix;
+               }
+               if ( first ) {
+                       if ( opt_course ) {
+                               wpt->course = 0;
+                       }
+                       if ( opt_speed ) {
+                               wpt->speed = 0;
+                       }
+                       first = 0;
+               }
+               else {
+                       if ( opt_course ) {
+                               wpt->course = heading( oldlat, oldlon,
+                                       wpt->latitude, wpt->longitude );
+                       }
+                       if ( opt_speed ) {
+                               if ( oldtime != wpt->creation_time ) {
+                                       wpt->speed = radtometers(gcdist( 
+                                           RAD(oldlat), RAD(oldlon), 
+                                           RAD(wpt->latitude), 
+                                           RAD(wpt->longitude))) /
+                                           labs(wpt->creation_time-oldtime);
+                               }       
+                               else {
+                                       wpt->speed = -999.0;
+                               }
+                       }
+               }
+               oldlat = wpt->latitude;
+               oldlon = wpt->longitude;
+               oldtime = wpt->creation_time;
+           }
+       }
+}
+
+
 /*******************************************************************************
 * option: "start" / "stop"
 *******************************************************************************/
@@ -637,7 +745,7 @@ trackfilter_range(void)             /* returns number of track points left after filtering
 static void
 trackfilter_init(const char *args) 
 {
-       
+
        int count = track_count();
 
        track_ct = 0;
@@ -679,12 +787,20 @@ trackfilter_process(void)
        
        opts = trackfilter_opt_count();
        if (opts == 0) opts = -1;               /* flag for do "pack" by default */
-
+       
        if (opt_move != NULL)                   /* Correct timestamps before any other op */
        {
            trackfilter_move();
            if (--opts == 0) return;
        }
+       
+       if ( opt_speed || opt_course || opt_fix ) {
+           trackfilter_synth();
+           if ( opt_speed ) opts--;
+           if ( opt_course ) opts--;
+           if ( opt_fix ) opts--;
+           if ( !opts ) return;
+       }
 
        if ((opt_stop != NULL) || (opt_start != NULL))
        {